package gnss

import (
	"dgo/goutils/gis"
	"dgo/goutils/utils"
	"fmt"
)

/// 基站数据
/***
Message Number (“1005”= 0011 1110 1101) DF002 uint12 12
Reference Station ID DF003 uint12 12
Reserved for ITRF Realization Year DF021 uint6 6
GPS NaviIndicator DF022 bit(1) 1
GLONASS NaviIndicator DF023 bit(1) 1
Reserved for Galileo NaviIndicator DF024 bit(1) 1
Reference-Station NaviIndicator DF141 bit(1) 1
Antenna Reference Point ECEF-X DF025 int38 38
Single Receiver Oscillator NaviIndicator DF142 bit(1) 1
Reserved DF001 bit(1) 1
Antenna Reference Point ECEF-Y DF026 int38 38
Quarter Cycle NaviIndicator DF364 bit(2) 2
Antenna Reference Point ECEF-Z DF027 int38 38
TOTAL 152
*/
type GnssStation struct {
	MsgID                 uint16
	StationId             uint16 // 跟踪站ID
	Itrf                  int
	NaviIndicator         byte
	OscillatorIndicator   byte // Single Receiver Oscillator NaviIndicator
	Reserved              byte
	QuarterCycleIndicator byte
	Pos                   [3]float64 // x,y,z
}

func (this *GnssStation) CopyFrom(src *GnssStation) {
	this.MsgID = src.MsgID
	this.StationId = src.StationId
	this.Itrf = src.Itrf
	this.NaviIndicator = src.NaviIndicator
	this.OscillatorIndicator = src.OscillatorIndicator
	this.Reserved = src.Reserved
	this.QuarterCycleIndicator = src.QuarterCycleIndicator
	this.Pos[0] = src.Pos[0]
	this.Pos[1] = src.Pos[1]
	this.Pos[2] = src.Pos[2]
}

func (this *GnssStation) String() string {
	b, l, h := gis.EcefXyz2PosiLatLngH(this.Pos[0], this.Pos[1], this.Pos[2])
	return fmt.Sprintf("[%d],StationID:%d, ITRF:%d, NaviIndicator:(%d)%s, xyz:(%.4f %.4f %.4f), blh:%.9f %.9f %.4f, Oscillator NaviIndicator:%d, Quarter Cycle NaviIndicator:%d",
		this.MsgID, this.StationId, this.Itrf, this.NaviIndicator, this.NaviIndicatorText(), this.Pos[0], this.Pos[1], this.Pos[2], b, l, h,
		this.OscillatorIndicator, this.QuarterCycleIndicator)
}

func (this *GnssStation) NaviIndicatorText() string {
	rval := ""
	if ((this.NaviIndicator >> (3 - 0)) & 1) == 1 {
		rval += "GPS,"
	}

	if ((this.NaviIndicator >> (3 - 1)) & 1) == 1 {
		rval += "GLO,"
	}

	if ((this.NaviIndicator >> (3 - 2)) & 1) == 1 {
		rval += "GLA,"
	}

	if ((this.NaviIndicator >> (3 - 3)) & 1) == 1 {
		rval += "REF,"
	}

	return rval
}

func (this *GnssStation) SetXyz(x, y, z float64) {
	this.Pos[0], this.Pos[1], this.Pos[2] = x, y, z
}

func (this *GnssStation) Xyz() (x, y, z float64) {
	return this.Pos[0], this.Pos[1], this.Pos[2]
}

func (this *GnssStation) Blh() (b, l, h float64) {
	b, l, h = gis.EcefXyz2PosiLatLngH(this.Pos[0], this.Pos[1], this.Pos[2])
	return
}

func (this *GnssStation) SetNaviIndicator(idx int, b byte) {
	mask := U8_1 << (3 - idx)
	if b == 1 {
		this.NaviIndicator |= mask
	} else {
		this.NaviIndicator &= ^mask
	}
}

/*
**

	startBitN 从msgid后面的跟踪站ID开始
	1005/1006都可以
*/
func DecodeRtcm1005(staRec *GnssStation, buf []byte, startBitN int) (endBitN int) {
	defer func() { // 捕捉异常
		if err := recover(); err != nil {
			utils.Log.Err("解码rtcm,msm出现了异常:", err)
			endBitN = -1
			return
		}
	}()
	staRec.StationId = GetBitU16(buf, startBitN, 12)
	startBitN += 12
	staRec.Itrf = int(GetBitU8(buf, startBitN, 6))
	startBitN += 6
	staRec.NaviIndicator = GetBitU8(buf, startBitN, 4)
	startBitN += 4
	{
		v1 := GetBitI64(buf, startBitN, 38)
		//fmt.Println(v1)
		staRec.Pos[0] = utils.Round64(float64(v1)*0.0001, 5)
		startBitN += 38
	}
	staRec.OscillatorIndicator = GetBitU8(buf, startBitN, 1)
	startBitN += 1
	staRec.Reserved = GetBitU8(buf, startBitN, 1)
	startBitN += 1
	{
		v1 := GetBitI64(buf, startBitN, 38)
		//fmt.Println(v1)
		staRec.Pos[1] = utils.Round64(float64(v1)*0.0001, 5)
		startBitN += 38
	}
	staRec.QuarterCycleIndicator = GetBitU8(buf, startBitN, 2)
	startBitN += 2

	{
		v1 := GetBitI64(buf, startBitN, 38)
		//fmt.Println(v1)
		staRec.Pos[2] = utils.Round64(float64(v1)*0.0001, 5)
		startBitN += 38
	}
	return startBitN
}

/*
适合 1005, 1006, 1033, msm4, msm5, msm7
*/
func RtcmBufSetStationId(rtcmBuf []byte, staid uint16) {
	SetBitU16(rtcmBuf, 24+12, 12, staid)
}

func RtcmBufMsg1005Set(rtcmBuf []byte, staid uint16, oscillator byte) {
	SetBitU16(rtcmBuf, 24+12, 12, staid)
	SetBitU8(rtcmBuf, 24+72, 1, oscillator)
}

func RtcmBufMsg1005SetXyz(rtcmBuf []byte, x, y, z float64) {
	startBitN := 24 + 12 + 12 + 6 + 4
	{ // x
		v1 := int64(RoundU(x * 10000))
		SetBitI64(rtcmBuf, startBitN, 38, v1)
		startBitN += 38
	}
	startBitN += 1 + 1
	{
		v1 := int64(RoundU(y * 10000))
		SetBitI64(rtcmBuf, startBitN, 38, v1)
		startBitN += 38
	}

	startBitN += 2
	{
		v1 := int64(RoundU(z * 10000))
		SetBitI64(rtcmBuf, startBitN, 38, v1)
		startBitN += 38
	}
}

/*
**

	startBitN 从MsgID开始
	1005/1006都可以
*/
func DecodeRtcm1005V1(staRec *GnssStation, buf []byte, startBitN int) (endBitN int) {
	defer func() { // 捕捉异常
		if err := recover(); err != nil {
			utils.Log.Err("解码rtcm,msm出现了异常:", err)
			endBitN = -1
			return
		}
	}()
	staRec.MsgID = GetBitU16(buf, startBitN, 12)
	startBitN += 12

	staRec.StationId = GetBitU16(buf, startBitN, 12)
	startBitN += 12
	staRec.Itrf = int(GetBitU8(buf, startBitN, 6))
	startBitN += 6
	staRec.NaviIndicator = GetBitU8(buf, startBitN, 4)
	startBitN += 4
	{
		v1 := GetBitI64(buf, startBitN, 38)
		//fmt.Println(v1)
		staRec.Pos[0] = utils.Round64(float64(v1)*0.0001, 5)
		startBitN += 38
	}
	staRec.OscillatorIndicator = GetBitU8(buf, startBitN, 1)
	startBitN += 1
	staRec.Reserved = GetBitU8(buf, startBitN, 1)
	startBitN += 1
	{
		v1 := GetBitI64(buf, startBitN, 38)
		//fmt.Println(v1)
		staRec.Pos[1] = utils.Round64(float64(v1)*0.0001, 5)
		startBitN += 38
	}
	staRec.QuarterCycleIndicator = GetBitU8(buf, startBitN, 2)
	startBitN += 2

	{
		v1 := GetBitI64(buf, startBitN, 38)
		//fmt.Println(v1)
		staRec.Pos[2] = utils.Round64(float64(v1)*0.0001, 5)
		startBitN += 38
	}
	return startBitN
}

func EncodeRtcm1005(rec *GnssStation, buf []byte, startBitN int) (endBitN int) {
	SetBitU16(buf, startBitN, 12, 1005)
	startBitN += 12
	SetBitU16(buf, startBitN, 12, uint16(rec.StationId))
	startBitN += 12
	SetBitU8(buf, startBitN, 6, uint8(rec.Itrf))
	startBitN += 6
	SetBitU8(buf, startBitN, 4, rec.NaviIndicator)
	startBitN += 4

	{
		v1 := int64(RoundU(rec.Pos[0] * 10000))
		SetBitI64(buf, startBitN, 38, v1)
		startBitN += 38
	}
	SetBitU8(buf, startBitN, 1, rec.OscillatorIndicator)
	startBitN += 1
	SetBitU8(buf, startBitN, 1, rec.Reserved)
	startBitN += 1
	{
		v1 := int64(RoundU(rec.Pos[1] * 10000))
		SetBitI64(buf, startBitN, 38, v1)
		startBitN += 38
	}

	SetBitU8(buf, startBitN, 2, rec.QuarterCycleIndicator)
	startBitN += 2

	{
		v1 := int64(RoundU(rec.Pos[2] * 10000))
		SetBitI64(buf, startBitN, 38, v1)
		startBitN += 38
	}
	return startBitN
}

func EncodeRtcm1005_ALL(rec *GnssStation, bb *utils.BytesBuilder, startIdx int) (byteN int) {
	bb.CheckSize(startIdx, 25) // 3 + 19 + 3 end crc
	bb.Replace(startIdx, []byte{0xD3, 0, 0})

	byteN = 3
	bitsN := EncodeRtcm1005(rec, bb.Buff(startIdx+3, 19), 0)
	byteN += bitsN / 8
	if bitsN%8 > 0 {
		byteN++
	}

	// 长度
	bb.SetBitU16(startIdx, 8+6, 10, uint16(byteN-3))
	crcBuf := bb.Buff(startIdx, byteN) // 3:同步标记 + 保留位 + 长度（RTCM消息体）(10bit)
	crc1 := utils.CRC24QBuf(crcBuf)
	bb.SetBitU32(startIdx+byteN, 0, 24, uint32(crc1))
	byteN += 3
	bb.Delete2End(startIdx + byteN)
	return
}
